﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;

namespace Marmat.Template.WinForm
{
    /// <summary>
    /// 左边菜单
    /// </summary>
    public partial class LeftMenu : UserControl
    {
        public LeftMenu()
        {
            InitializeComponent();
            SetStyle(ControlStyles.ResizeRedraw, true); //尺寸变化后绘制
            SetStyle(ControlStyles.Opaque, false); //改善绘图质量
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
        }

        private List<LeftMenuItem> menuItems = new List<LeftMenuItem>();

        /// <summary>
        /// 鼠标点击菜单委托
        /// </summary>
        /// <param name="menuItem"></param>
        public delegate void MenuEventHandler(LeftMenuItem menuItem);

        /// <summary>
        /// 鼠标点击菜单后执行
        /// </summary>
        [Description("鼠标点击菜单后执行")]
        public event MenuEventHandler MenuItemClick;

        public void AddControls(params LeftMenuItem[] items)
        {
            var group = items.Where(x => x.IsTitle).OrderBy(x => x.Sequnce);
            var menus = items.Where(x => !x.IsTitle).OrderBy(x => x.Sequnce);
            this.menuItems.AddRange(group);
            this.menuItems.AddRange(menus);
            this.Invalidate();
        }

        /// <summary>
        /// 覆盖菜单
        /// </summary>
        /// <param name="items"></param>
        public void CoverControls(params LeftMenuItem[] items)
        {
            this.menuItems.Clear();
            this.AddControls(items);
        }

        private void LeftMenu_Paint(object sender, PaintEventArgs e)
        {
            int y = 0;

            foreach (var item in this.menuItems)
            {
                var rec = new Rectangle(e.ClipRectangle.X, y, this.Width, 40);
                drawItemSelsect(item, rec,true);
                //if (!this.rectangles.ContainsKey(item))
                this.rectangles[item] = rec;
                y += 40;
                if (item.IsTitle)
                {
                    foreach (var menuItem in item.Children)
                    {
                        if (item.isOpen)
                        {
                            rec = new Rectangle(e.ClipRectangle.X, y, this.Width, 40);
                            drawItemSelsect(menuItem, rec);
                            y += 40;
                        }
                        this.rectangles[menuItem] = rec;
                    }
                }
            }

            void drawItemSelsect(LeftMenuItem item, Rectangle rec, bool isFirst=false)
            {
                if (rec.Contains(this.mousePoint))
                {
                    if (item.IsTitle)
                        this.ItemPrint(e, rec, Color.FromArgb(0, 45, 100), item, y, isFirst);
                    else this.ItemPrint(e, rec, Color.FromArgb(120, 149, 255), item, y, isFirst);
                }
                else
                {
                    if (item.IsTitle) this.ItemPrint(e, rec, Color.FromArgb(18, 65, 120), item, y, isFirst);
                    else this.ItemPrint(e, rec, Color.FromArgb(38, 85, 140), item, y, isFirst);
                }
            }
        }

        private void ItemPrint(PaintEventArgs e, Rectangle rec, Color color, LeftMenuItem item, int y, bool isFirst = false)
        {
            Rectangle textRec;
            Font font;
            using (Brush brush = new SolidBrush(color))
                e.Graphics.FillRectangle(brush, rec);
            using (Brush brush = new SolidBrush(Color.White))
            {
                StringFormat format = new StringFormat();
                format.FormatFlags = StringFormatFlags.NoClip;
                var _rec = new Rectangle(e.ClipRectangle.X + 10, y + (40 - 25) / 2, 25, 25);
                textRec = new Rectangle(e.ClipRectangle.X + 43, y + (40 - 18) / 2, this.Width, 40);

                if (item.IsTitle)
                {
                    textRec = new Rectangle(e.ClipRectangle.X + 43, y + (40 - 18) / 2, this.Width, 40);
                    font = new Font("微软雅黑", 11F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(134)));
                    Rectangle imgrec = new Rectangle(this.Width - 25, y + (40 - 18) / 2, 16, 16);
                    if (item.isOpen) e.Graphics.DrawImage(Properties.Resources.上, imgrec);
                    else e.Graphics.DrawImage(Properties.Resources.下, imgrec);
                }
                else
                {
                    font = this.Font;
                    if (isFirst)
                    {
                        textRec = new Rectangle(e.ClipRectangle.X + 43, y + (40 - 18) / 2, this.Width, 40);
                        font = new Font("微软雅黑", 11F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(134)));
                        Rectangle imgrec = new Rectangle(this.Width - 25, y + (40 - 18) / 2, 16, 16);
                    }
                    else
                    {
                        textRec = new Rectangle(e.ClipRectangle.X + 53, y + (40 - 18) / 2, this.Width, 40);
                        _rec = new Rectangle(e.ClipRectangle.X + 53 - 28, y + (40 - 20) / 2, 20, 20);
                    }
                }

                e.Graphics.DrawImage(item.Icon, _rec);
                e.Graphics.DrawString(item.Caption, font, brush, textRec, format);
            }
        }

        private LeftMenuItem selsetMenuItem;
        /// <summary>
        /// 鼠标位置
        /// </summary>
        private Point mousePoint = new Point(-1, -1);
        private Dictionary<LeftMenuItem, Rectangle> rectangles = new Dictionary<LeftMenuItem, Rectangle>();

        protected override void OnMouseDown(MouseEventArgs e)
        {
            foreach (var item in this.rectangles)
            {
                if (item.Key.IsTitle && item.Value.Contains(this.mousePoint)) { 
                    item.Key.isOpen = !item.Key.isOpen;
                    break;
                }
                else if (item.Value.Contains(this.mousePoint))
                {
                    this.MenuItemClick?.Invoke(item.Key);
                    break;
                }
            }
            base.OnMouseDown(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            this.mousePoint = e.Location;
            bool bo = false;
            foreach (var item in rectangles)
            {
                if (item.Value.Contains(e.Location))
                {
                    if (this.selsetMenuItem != item.Key)
                    {
                        this.selsetMenuItem = item.Key;
                        this.Invalidate();
                        bo = true;
                        break;
                    }
                }
            }
            if (!bo)
            {
                this.selsetMenuItem = null;
                this.Invalidate();
            }
            base.OnMouseMove(e);
        }

        private void LeftMenu_MouseLeave_1(object sender, EventArgs e)
        {
            this.mousePoint = new Point(-1, -1);
            this.Invalidate();
        }
    }

    /// <summary>
    /// 左边菜单子项
    /// </summary>
    public class LeftMenuItem
    {
        internal LeftMenuItem parent;

        public LeftMenuItem() { }
        public LeftMenuItem(LeftMenuItem parent)
        {
        }
        /// <summary>
        /// 菜单父节点
        /// </summary>
        public LeftMenuItem Parent => parent;
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 显示名称
        /// </summary>
        public string Caption { get; set; }

        /// <summary>
        ///  顺序
        /// </summary>
        public double Sequnce { get; set; }

        /// <summary>
        /// 图标
        /// </summary>
        public Image Icon { get; set; }

        /// <summary>
        /// 附加属性
        /// </summary>
        public object Tag { get; set; }

        /// <summary>
        ///  组的打开状态
        /// </summary>
        internal bool isOpen { get; set; }

        public bool IsTitle
        {
            get
            {
                if (this.children != null)
                    return this.children.Count > 0;
                else return false;
            }
        }


        /// <summary>
        /// 字节集合
        /// </summary>
        public LeftMenuItemChildren Children
        {
            get
            {
                if (children is null)
                    children = new LeftMenuItemChildren(this);
                return children;
            }
        }
        private LeftMenuItemChildren children;

    }

    /// <summary>
    /// 菜单子节点
    /// </summary>
    public class LeftMenuItemChildren : IEnumerable<LeftMenuItem>
    {
        private LeftMenuItem Parent;
        public LeftMenuItemChildren(LeftMenuItem item)
        {
            Parent = item;
        }
        private List<LeftMenuItem> items = new List<LeftMenuItem>();
        public IEnumerator<LeftMenuItem> GetEnumerator()
        {
            return items.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return items.GetEnumerator();
        }
        /// <summary>
        ///  将对象添加到 System.Collections.Generic.List`1 的结尾处。
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public void Add(LeftMenuItem column)
        {
            column.parent = Parent;
            this.items.Add(column);
        }
        /// <summary>
        ///  获取 System.Collections.Generic.List`1 中包含的元素数。
        /// </summary>
        public int Count => items.Count;
    }
}
